﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace NetLogger
{
	/// <summary>
	/// Defines a message sent or received between loggers
	/// </summary>
	public class NetMessage : INetPost, IEquatable<NetMessage>
	{
		private int _activationId;
		private Guid _id;
		private string _fromLoggerId;
		private string _toLoggerId;
		private DateTimeOffset _postTime;
		private string _body;
		private string _header;

		/// <summary>
		/// Used to represent "all loggers" in the DB column that defines who the message is to
		/// </summary>
		private const string ToAll = "*";

		/// <summary>
		/// Constructs a message from user-supplied data in the UI
		/// </summary>
		/// <param name="activationId">Unique ID of the current net activation</param>
		/// <param name="fromLoggerId">Callsign of the current logger that is sending the message</param>
		/// <param name="toLoggerId">Callsign or "all loggers" where the message will be sent</param>
		/// <param name="body">Text of the message</param>
		public NetMessage( int activationId, string fromLoggerId, string toLoggerId, string body )
		{
			_activationId = activationId;
			_fromLoggerId = fromLoggerId;
			_id = Guid.NewGuid();
			_toLoggerId = ( toLoggerId == Properties.Resources.AllLoggers ? ToAll : toLoggerId );
			_postTime = DateTimeOffset.UtcNow;
			_body = body;
		}

		/// <summary>
		/// Constructs a message from downloaded data
		/// </summary>
		/// <param name="node">XML node containing the message definition</param>
		public NetMessage( XElement node )
		{
			foreach ( var item in node.Elements() )
			{
				switch ( item.Name.LocalName )
				{
					case "net_id":
						_activationId = ( int ) item;
						break;
					case "message_id":
						_id = Guid.Parse( NetPost.DecodedString( item ) );
						break;
					case "message_time":
						_postTime = NetPost.FromMySQLDate( item );
						break;
					case "message_body":
						_body = NetPost.DecodedString( item );
						break;
					case "logger_id":
						_fromLoggerId = NetPost.DecodedString( item );
						break;
					case "to_logger_id":
						_toLoggerId = NetPost.DecodedString( item );
						break;
				}
			}
		}

		/// <summary>
		/// True if the message was sent by the current logger
		/// </summary>
		public bool IsFromMe
		{
			get
			{
				return _fromLoggerId == NetActivation.Instance.LoggerId;
			}
		}

		/// <summary>
		/// True if the message was sent from one logger directly to another
		/// </summary>
		public bool IsPrivate
		{
			get
			{
				return _toLoggerId != ToAll;
			}
		}

		/// <summary>
		/// Header text to display above the message in the UI
		/// </summary>
		public string Header
		{
			get
			{
				return _header ?? ( _header = string.Format( Properties.Resources.MessageHeaderFormat,
					_fromLoggerId, IsPrivate ? _toLoggerId : Properties.Resources.AllLoggers,
					_postTime.ToLocalTime().ToString( Properties.Resources.TimeFormat ) ) );
			}
		}

		/// <summary>
		/// Message text to display in the UI
		/// </summary>
		public string Body
		{
			get
			{
				return _body;
			}
		}

		/// <summary>
		/// Callsign or "all loggers" that a reply to this message should be sent to
		/// </summary>
		public string DefaultReplyTo
		{
			get
			{
				string
					privateAddress = ( IsFromMe ? _toLoggerId : _fromLoggerId );

				return IsPrivate ? privateAddress : Properties.Resources.AllLoggers;
			}
		}

		public NetPost GetNetPost()
		{
			NetPost
				post = new NetPost( NetActivation.MessagePage );

			post.Data[ "net_id" ] = _activationId.ToString();
			post.Data[ "message_id" ] = _id.ToString();
			post.Data[ "message_time" ] = NetPost.ToMySQLDate( _postTime );
			post.Data[ "message_body" ] = _body;
			post.Data[ "logger_id" ] = _fromLoggerId;
			post.Data[ "to_logger_id" ] = _toLoggerId;

			return post;
		}

		public bool Equals( NetMessage other )
		{
			return _id == other._id;
		}
	}
}
